/**
 * jsf_demo
 * zhanjung
 */
package com.junhong.forum.datamodel;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

import com.junhong.auth.common.Login;
import com.junhong.auth.entity.User;
import com.junhong.forum.common.Constants;
import com.junhong.forum.entity.ForumCategory;
import com.junhong.forum.entity.ForumThread;
import com.junhong.forum.service.ThreadEjb;

/**
 * @author zhanjung
 * 
 */
public class LazyThreadDataModel extends LazyDataModel<ForumThread> {

	/**
	 * 
	 */
	private static final long	serialVersionUID	= -8730272180146226564L;

	private ForumCategory		parentCategory;
	private User				user;
	// check where it is from: MAIN, or MYPOST in the user profile page
	private String				source				= "-1";

	@EJB
	private ThreadEjb			threadEjb;

	@Inject
	private Login				login;

	public LazyThreadDataModel() {
	}

	public LazyThreadDataModel(ForumCategory category) {
		this.parentCategory = category;
	}

	@Override
	public List<ForumThread> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
		List<ForumThread> result = new ArrayList<ForumThread>();
		// For MyPost page.
		if (this.source.equals(Constants.USER_TAB_MYPOST)) {
			// load the threads for the given user
			int dataSize = threadEjb.getForumThreadCountByOwner(user, false);
			this.setRowCount(dataSize);

			// paginate
			result = threadEjb.getThreadList(user, first, pageSize);

		} else if (this.source.equals(Constants.USER_TAB_MYWATCHLIST)) {
			User currUser = login.getCurrentUser();
			result = login.getUserAllStickyThreads(currUser);
			this.setRowCount(result.size());
		}
		// for the regular thread everyone will navigate through category and thread
		else {

			parentCategory = (ForumCategory) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(Constants.BelongingCategory);
			boolean isUserAccessableToLockedThreads = login.isUserCategory_Owner(parentCategory) || login.isUserInSysadmin();
			// rowCount
			int dataSize = threadEjb.getForumThreadCountByCategory(parentCategory, isUserAccessableToLockedThreads);
			this.setRowCount(dataSize);

			// paginate
			int toppedThreadsSize = 0;
			List<ForumThread> toppedThreadList = new ArrayList<ForumThread>();
			List<Integer> toppedThreadIdList = new ArrayList<Integer>();

			toppedThreadList = threadEjb.getToppedThreadList(parentCategory);
			toppedThreadsSize = toppedThreadList.size();
			for (ForumThread ft : toppedThreadList) {
				toppedThreadIdList.add(ft.getId());
			}

			if (dataSize > pageSize) {

				/*
				 * this part is pretty confusing. need to consider carefully before
				 * changing the logic. you could draw a diagram for detail analysis.
				 */
				if (toppedThreadsSize < pageSize) {
					if (first >= toppedThreadsSize) {
						result = threadEjb.getThreadListByCategory(parentCategory, first - toppedThreadsSize, pageSize, toppedThreadIdList,
								isUserAccessableToLockedThreads);
					} else {
						result.addAll(toppedThreadList);
						result.addAll(threadEjb.getThreadListByCategory(parentCategory, first, pageSize - toppedThreadsSize, toppedThreadIdList,
								isUserAccessableToLockedThreads));
					}

				} else {
					if (first >= toppedThreadsSize) {
						result = threadEjb.getThreadListByCategory(parentCategory, first - toppedThreadsSize, pageSize, toppedThreadIdList,
								isUserAccessableToLockedThreads);
					} else if (first + pageSize < toppedThreadsSize) {
						result = toppedThreadList.subList(first, first + pageSize);
					} else {
						/*
						 * when first<stickthreadsize and first+pagesize
						 * >stickthreadsize
						 */
						result.addAll(toppedThreadList.subList(first, toppedThreadsSize));
						result.addAll(threadEjb.getThreadListByCategory(parentCategory, 0, pageSize - (toppedThreadsSize - first),
								toppedThreadIdList, isUserAccessableToLockedThreads));
					}

				}
			} else {
				result.addAll(toppedThreadList);
				result.addAll(threadEjb.getThreadListByCategory(parentCategory, 0, dataSize - toppedThreadsSize, toppedThreadIdList,
						isUserAccessableToLockedThreads));
			}
		}
		return result;
	}

	public ForumCategory getParentCategory() {
		return parentCategory;
	}

	public void setParentCategory(ForumCategory parentCategory) {
		this.parentCategory = parentCategory;
	}

	/**
	 * @return the source
	 */
	public String getSource() {
		return source;
	}

	/**
	 * @param source
	 *            the source to set
	 */
	public void setSource(String source) {
		this.source = source;
	}

	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	/**
	 * @param user
	 *            the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}
}